#pragma once
#include "BaseStack.h"

template <typename T>
class ArrayStack : public BaseStack<T>
{
private :
	const int m_nMaxSize;
	T* m_oStack;
	int m_nCurrentIndex;
public :
	ArrayStack(int a_nMaxSize);
	~ArrayStack();

	virtual void push(T a_oData);
	virtual T pop();
	virtual bool canPush();
	virtual bool canPop();
	virtual int getDataCount();

};

template <typename T>
ArrayStack<T>::ArrayStack(int a_nMaxSize) : m_nMaxSize(a_nMaxSize)
{
	this->m_oStack = new T[a_nMaxSize];
	this->m_nCurrentIndex = -1;
}

template <typename T>
ArrayStack<T>::~ArrayStack()
{
	this->m_nCurrentIndex = -1;
	delete[] this->m_oStack;
}

template <typename T>
void ArrayStack<T>::push(T a_oData) 
{
	if(canPush() == false) 
	{
		throw DSFullFilledException();
	}

	m_oStack[++m_nCurrentIndex] = a_oData;
}

template <typename T>
T ArrayStack<T>::pop() 
{
	if(canPop() == false) {
		throw DSEmptyException();
	}

	return m_oStack[m_nCurrentIndex--];
}

template <typename T>
bool ArrayStack<T>::canPush() 
{
	int currentCount = m_nCurrentIndex + 1;
	return currentCount < this->m_nMaxSize;
}

template <typename T>
bool ArrayStack<T>::canPop() 
{
	return m_nCurrentIndex > -1;
}

template <typename T>
int ArrayStack<T>::getDataCount()
{
	return m_nCurrentIndex + 1;
}